#include <cstdlib>
#include <stdexcept>
#include <algorithm>
#include "shortread.h"

using namespace std;

ShortRead::ShortRead()
    {

    }

ShortRead::~ShortRead()
    {

    }

void ShortRead::printFastQ(std::ostream& out) const
    {
    out	<< name() << "\n"
	<< sequence() << "\n"
	<< name2() << "\n"
	<< qualities() << "\n"
	;
    }

/*****************************************************/
/*****************************************************/
/*****************************************************/



DefaultShortRead::DefaultShortRead()
    {
    }


DefaultShortRead::~DefaultShortRead()
    {
    free(_name);
    free(_seq);
    free(_name2);
    free(_qual);
    delete _sequence;
    delete _qualities;
    }


DefaultShortRead*
DefaultShortRead::read(LineReader* in)
    {
    DefaultShortRead* sread=NULL;
    char* name=NULL;
    size_t len;
    size_t read_len;
    char* seq=NULL;
    char* name2=NULL;
    char* qual=NULL;

    if(in->eof()) return NULL;

    char* p=in->readLine(&len);
    if(p==NULL) return NULL;
    name=safeStrndup(p,len);

    p=in->readLine(&read_len);
    if(p==NULL) goto fail;
    seq=safeStrndup(p,read_len);

    p=in->readLine(&len);
    if(p==NULL) goto fail;
    name2=safeStrndup(p,len);

    p=in->readLine(&len);
    if(p==NULL) goto fail;
    if(len!=read_len)
	{
	throw new std::runtime_error("Read-length!=qual-length!");
	}
    qual=safeStrndup(p,len);


    sread=new DefaultShortRead;
    sread->_len=read_len;
    sread->_name=name;
    sread->_name2=name2;
    sread->_seq=seq;
    std::transform(sread->_seq,sread->_seq+read_len,sread->_seq,normalize_base);
    sread->_qual=qual;
    sread->_sequence= new CStringWapper(sread->_seq,sread->_len);
    sread->_qualities= new CStringWapper(sread->_qual,sread->_len);

    fail:
	if(sread==NULL)
	    {
	    free(name);
	    free(seq);
	    free(name2);
	    free(qual);
	    }
    return sread;
    }


const char* DefaultShortRead::name() const
    {
    return this->_name;
    }

const char* DefaultShortRead::name2() const
    {
    return this->_name2;
    }

const CharSequence* DefaultShortRead::sequence() const
    {
    return this->_sequence;
    }
const CharSequence* DefaultShortRead::qualities() const
    {
    return this->qualities();
    }

const CharSequence* DefaultShortRead::delegate() const
    {
    return this->_sequence;
    }
/***************************************************/

TrimmedShortRead::TrimmedShortRead(
	const ShortRead* owned,
	size_type pos,
	size_type len):_owned(owned)
    {
    this->_subseq=new SubStringSequence(owned->sequence(),pos,len);
    this->_qual=new SubStringSequence(owned->qualities(),pos,len);
    }

TrimmedShortRead::~TrimmedShortRead()
    {
    delete _qual;
    delete _subseq;
    }
const char* TrimmedShortRead::name() const
    {
    return _owned->name();
    }
const char* TrimmedShortRead::name2() const
    {
    return _owned->name2();
    }
const CharSequence* TrimmedShortRead::delegate() const
    {
    return _subseq;
    }

const CharSequence* TrimmedShortRead::sequence() const
    {
    return _subseq;
    }
const CharSequence* TrimmedShortRead::qualities() const
    {
    return _qual;
    }
